
#include <windows.h>

#include "Clock.h"

#include <stdio.h>

//
// This class manages time for the scheduler
//
// For clarity, this keeps tracks of both real time and virtual time.
//
// System time ....... real time (zero-based)
// Simulation time ... virtual time (zero-based)
// Frame ............. current frame


Clock::Clock()
{
	timeBeginPeriod(1); // set win32 time resolution
	Reset();
}

Clock::~Clock()
{
	timeEndPeriod(1); // release win32 time resolution
}

void Clock::Reset()
{
	//
	// reset clock to startup conditions
	//
	m_running = false;

	m_thisTime = timeGetTime();
	m_lastTime = m_thisTime;

	m_systemTime = 0;
	m_pauseTime = 0;
	m_systemOffset = m_thisTime;

	m_frameCount = 0;
	m_frameStart = 0;
	m_frameEnd = 0;

	m_simTime = 0;
	m_simOffset = 0;
}

void Clock::Run()
{
	if (!m_running)
	{
		Update();
		m_simOffset += (m_systemTime - m_pauseTime);
#ifdef SHOW_SCHEDULE_INFO
		ShowDebug("Clock: started, %u ms elapsed since last stop\n", (int)(m_systemTime - m_pauseTime));
#endif
	}
	m_running = true;
}
void Clock::Stop()
{
	if (m_running)
	{
		Update();
		m_pauseTime = m_systemTime;
#ifdef SHOW_SCHEDULE_INFO
		ShowDebug("Clock: stopped, paused at %u ms\n", (int)m_pauseTime);
#endif
	}
	m_running = false;
}

void Clock::Update()
{
	// get windows' idea of current time
	int elapsed = 0;
	m_lastTime = m_thisTime;
	m_thisTime = timeGetTime();

	// convert to elapsed time
	// also handle rollover, which happens every 2^32 milliseconds
	if (m_thisTime < m_lastTime)
		elapsed = m_lastTime - m_thisTime;
	else
		elapsed = m_thisTime - m_lastTime;

	// system time is real time and never pauses
	m_systemTime += elapsed;
	//	printf("<CLOCK> update, system=%u, elapsed=%u\n", m_systemTime, elapsed);
}

void Clock::BeginFrame()
{
	// Begin a new frame. This method is normally called
	// immediately AFTER rendering the previous frame, and
	// sets the context for all work which will be rendered
	// on the next frame.
	//
	// This method increments the frame count and samples real
	// time to determine the elapsed time since the last frame.
	//
	// <Render frame n>
	// <Begin frame n+1>
	// <Task1>
	// <Task2>
	// <Task3...>
	// <Render frame n+1>
	//

	m_frameCount++;

	Update(); // update system time


	if (m_running)
	{
		m_frameStart = m_frameEnd; // start of this frame = end of last frame
		m_frameEnd = m_systemTime - m_simOffset; // end of this frame = current time
		m_simTime = m_frameStart; // set simulation time to start of frame
	}
#ifdef SHOW_SCHEDULE_INFO
	ShowDebug("Clock: begin frame %u (begin %u, end %u), sys=%u, sim=%u (%u)\n", (int)m_frameCount,(int)m_frameStart,(int)m_frameEnd, (int)m_systemTime, (int)m_simTime, (int)m_simOffset);
#endif
}

void Clock::AdvanceTo(int newTime)
{
	if (m_running && newTime >= m_simTime)
	{
		m_simTime = newTime;
		//		printf("<CLOCK> advance to %u\n", m_simTime);
	}
}

void Clock::AdvanceToEnd()
{
	if (m_running)
	{
		m_simTime = m_frameEnd;
		//		printf("<CLOCK> advance to %u (end)\n", m_simTime);
	}
}


